from flask import Blueprint, request, current_app
from app.utils.mysql_db import get_db_connection, get_db_cursor, DatabaseLogger
from app.utils.logger import FlinkLogger, log_api_call, log_database_operation


bp = Blueprint("flink_monitor_config", __name__)


@bp.get("")
@log_api_call("flink_monitor_config.list_configs")
def list_configs():
    """获取配置列表，支持分页、搜索、按分组过滤"""
    current_app.logger.info("Listing flink monitor configs")
    
    # 获取查询参数
    config_key = request.args.get("config_key")
    config_group = request.args.get("config_group")
    is_active = request.args.get("is_active")
    is_sensitive = request.args.get("is_sensitive")
    page = request.args.get("page", 1, type=int)
    size = request.args.get("size", 20, type=int)
    
    # 获取排序参数（默认按 sort_order, config_key 排序）
    sort_field = request.args.get("sort", "sort_order")
    sort_order = request.args.get("order", "asc").upper()
    
    # 构建查询条件
    where = []
    params = []
    
    if config_key:
        where.append("config_key LIKE %s")
        params.append(f"%{config_key}%")
    
    if config_group:
        where.append("config_group = %s")
        params.append(config_group)
    
    if is_active is not None and is_active != '':
        where.append("is_active = %s")
        params.append(int(is_active))
    
    if is_sensitive is not None and is_sensitive != '':
        where.append("is_sensitive = %s")
        params.append(int(is_sensitive))
    
    where_sql = (" WHERE " + " AND ".join(where)) if where else ""
    
    # 白名单验证排序字段
    valid_sort_fields = [
        "config_key", "config_group", "config_type", "sort_order", 
        "is_active", "is_required", "is_sensitive", "restart_required",
        "created_time", "modified_time"
    ]
    if sort_field not in valid_sort_fields:
        sort_field = "sort_order"
    if sort_order not in ["ASC", "DESC"]:
        sort_order = "ASC"
    
    # 默认排序：先按 sort_order，再按 config_key
    if sort_field == "sort_order":
        order_by_clause = f"ORDER BY sort_order {sort_order}, config_key ASC"
    else:
        order_by_clause = f"ORDER BY {sort_field} {sort_order}"
    
    conn = get_db_connection()
    try:
        with conn.cursor() as cur:
            # 获取总数（考虑筛选条件）
            count_sql = f"SELECT COUNT(*) as total FROM flink_cluster_system_config {where_sql}"
            cur.execute(count_sql, params)
            total_result = cur.fetchone()
            total = total_result['total'] if total_result else 0
            
            # 查询全局总数（不考虑筛选条件，用于统计卡片）
            cur.execute("SELECT COUNT(*) as total FROM flink_cluster_system_config")
            total_all_result = cur.fetchone()
            total_all = total_all_result['total'] if total_all_result else 0
            
            # 获取各分组的统计
            cur.execute("""
                SELECT 
                    config_group,
                    COUNT(*) as count
                FROM flink_cluster_system_config
                GROUP BY config_group
            """)
            group_stats = {row['config_group']: row['count'] for row in cur.fetchall()}
            
            # 获取分页数据
            offset = (page - 1) * size
            cur.execute(
                f"""
                SELECT 
                    id, config_key, config_group, config_value, config_type,
                    default_value, validation_rule, is_required, is_sensitive,
                    restart_required, is_active, sort_order, description,
                    created_time, modified_time
                FROM flink_cluster_system_config
                {where_sql}
                {order_by_clause}
                LIMIT %s OFFSET %s
                """,
                (*params, size, offset),
            )
            rows = cur.fetchall()
            
            # 格式化时间字段
            for row in rows:
                if row.get('created_time') and hasattr(row['created_time'], 'strftime'):
                    row['created_time'] = row['created_time'].strftime('%Y-%m-%d %H:%M:%S')
                if row.get('modified_time') and hasattr(row['modified_time'], 'strftime'):
                    row['modified_time'] = row['modified_time'].strftime('%Y-%m-%d %H:%M:%S')
                
                # 敏感信息处理：在列表中隐藏敏感配置的值
                if row.get('is_sensitive') == 1 and row.get('config_value'):
                    row['config_value'] = '******'
            
            return {
                "success": True,
                "message": "ok",
                "data": {
                    "rows": rows,
                    "total": total,
                    "total_all": total_all,
                    "group_stats": group_stats,
                    "page": page,
                    "size": size
                }
            }
    finally:
        conn.close()


@bp.get("/groups")
@log_api_call("flink_monitor_config.get_groups")
def get_groups():
    """获取所有配置分组列表"""
    current_app.logger.info("Getting config groups")
    
    conn = get_db_connection()
    try:
        with conn.cursor() as cur:
            cur.execute("""
                SELECT DISTINCT config_group, COUNT(*) as count
                FROM flink_cluster_system_config
                GROUP BY config_group
                ORDER BY config_group
            """)
            groups = cur.fetchall()
            
            return {
                "success": True,
                "message": "ok",
                "data": groups
            }
    finally:
        conn.close()


@bp.get("/<int:config_id>")
@log_api_call("flink_monitor_config.get_config")
def get_config(config_id):
    """获取单个配置详情"""
    current_app.logger.info(f"Getting config detail | id: {config_id}")
    
    conn = get_db_connection()
    try:
        with conn.cursor() as cur:
            cur.execute("""
                SELECT 
                    id, config_key, config_group, config_value, config_type,
                    default_value, validation_rule, is_required, is_sensitive,
                    restart_required, is_active, sort_order, description,
                    created_time, modified_time
                FROM flink_cluster_system_config
                WHERE id = %s
            """, (config_id,))
            row = cur.fetchone()
            
            if not row:
                return {
                    "success": False,
                    "message": "配置不存在",
                    "data": None
                }, 404
            
            # 格式化时间字段
            if row.get('created_time') and hasattr(row['created_time'], 'strftime'):
                row['created_time'] = row['created_time'].strftime('%Y-%m-%d %H:%M:%S')
            if row.get('modified_time') and hasattr(row['modified_time'], 'strftime'):
                row['modified_time'] = row['modified_time'].strftime('%Y-%m-%d %H:%M:%S')
            
            # 注意：详情接口返回真实的敏感值，供编辑使用
            # 前端会在显示时处理为 ****** 并提供显示/隐藏按钮
            
            return {
                "success": True,
                "message": "ok",
                "data": row
            }
    finally:
        conn.close()


@bp.post("")
@log_api_call("flink_monitor_config.create_config")
def create_config():
    """创建新配置"""
    data = request.get_json()
    current_app.logger.info(f"Creating config | key: {data.get('config_key')}")
    
    # 必填字段验证
    required_fields = ['config_key', 'config_group', 'config_value', 'config_type']
    for field in required_fields:
        if not data.get(field):
            return {
                "success": False,
                "message": f"缺少必填字段: {field}",
                "data": None
            }, 400
    
    conn = get_db_connection()
    try:
        with conn.cursor() as cur:
            # 检查配置键是否已存在
            cur.execute("SELECT id FROM flink_cluster_system_config WHERE config_key = %s", 
                       (data['config_key'],))
            if cur.fetchone():
                return {
                    "success": False,
                    "message": f"配置键 {data['config_key']} 已存在",
                    "data": None
                }, 400
            
            # 插入新配置
            cur.execute("""
                INSERT INTO flink_cluster_system_config (
                    config_key, config_group, config_value, config_type,
                    default_value, validation_rule, is_required, is_sensitive,
                    restart_required, is_active, sort_order, description
                ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
            """, (
                data['config_key'],
                data['config_group'],
                data['config_value'],
                data['config_type'],
                data.get('default_value'),
                data.get('validation_rule'),
                data.get('is_required', 0),
                data.get('is_sensitive', 0),
                data.get('restart_required', 0),
                data.get('is_active', 1),
                data.get('sort_order', 0),
                data.get('description')
            ))
            conn.commit()
            
            new_id = cur.lastrowid
            current_app.logger.info(f"Config created | id: {new_id} | key: {data['config_key']}")
            
            return {
                "success": True,
                "message": "配置创建成功",
                "data": {"id": new_id}
            }
    except Exception as e:
        conn.rollback()
        current_app.logger.error(f"Failed to create config | error: {str(e)}")
        return {
            "success": False,
            "message": f"创建配置失败: {str(e)}",
            "data": None
        }, 500
    finally:
        conn.close()


@bp.put("/<int:config_id>")
@log_api_call("flink_monitor_config.update_config")
def update_config(config_id):
    """更新配置"""
    data = request.get_json()
    current_app.logger.info(f"Updating config | id: {config_id}")
    
    conn = get_db_connection()
    try:
        with conn.cursor() as cur:
            # 检查配置是否存在
            cur.execute("SELECT id FROM flink_cluster_system_config WHERE id = %s", (config_id,))
            if not cur.fetchone():
                return {
                    "success": False,
                    "message": "配置不存在",
                    "data": None
                }, 404
            
            # 构建更新语句
            update_fields = []
            params = []
            
            # 允许更新的字段
            allowed_fields = {
                'config_group', 'config_value', 'config_type', 'default_value',
                'validation_rule', 'is_required', 'is_sensitive', 'restart_required',
                'is_active', 'sort_order', 'description'
            }
            
            for field in allowed_fields:
                if field in data:
                    update_fields.append(f"{field} = %s")
                    params.append(data[field])
            
            if not update_fields:
                return {
                    "success": False,
                    "message": "没有需要更新的字段",
                    "data": None
                }, 400
            
            params.append(config_id)
            
            cur.execute(
                f"UPDATE flink_cluster_system_config SET {', '.join(update_fields)} WHERE id = %s",
                params
            )
            conn.commit()
            
            current_app.logger.info(f"Config updated | id: {config_id}")
            
            return {
                "success": True,
                "message": "配置更新成功",
                "data": {"id": config_id}
            }
    except Exception as e:
        conn.rollback()
        current_app.logger.error(f"Failed to update config | id: {config_id} | error: {str(e)}")
        return {
            "success": False,
            "message": f"更新配置失败: {str(e)}",
            "data": None
        }, 500
    finally:
        conn.close()


@bp.delete("/<int:config_id>")
@log_api_call("flink_monitor_config.delete_config")
def delete_config(config_id):
    """删除配置"""
    current_app.logger.info(f"Deleting config | id: {config_id}")
    
    conn = get_db_connection()
    try:
        with conn.cursor() as cur:
            # 检查配置是否存在
            cur.execute("SELECT config_key FROM flink_cluster_system_config WHERE id = %s", (config_id,))
            row = cur.fetchone()
            if not row:
                return {
                    "success": False,
                    "message": "配置不存在",
                    "data": None
                }, 404
            
            config_key = row['config_key']
            
            # 删除配置
            cur.execute("DELETE FROM flink_cluster_system_config WHERE id = %s", (config_id,))
            conn.commit()
            
            current_app.logger.info(f"Config deleted | id: {config_id} | key: {config_key}")
            
            return {
                "success": True,
                "message": "配置删除成功",
                "data": None
            }
    except Exception as e:
        conn.rollback()
        current_app.logger.error(f"Failed to delete config | id: {config_id} | error: {str(e)}")
        return {
            "success": False,
            "message": f"删除配置失败: {str(e)}",
            "data": None
        }, 500
    finally:
        conn.close()

